package com.smart.community.user.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.cache.DataScopeInfo;
import com.smart.community.commons.enums.RoleCodeEnum;
import com.smart.community.commons.enums.SystemStatusEnum;
import com.smart.community.commons.exception.BusinessException;
import com.smart.community.commons.result.PageResult;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.feign.property.service.DataScopeFeign;
import com.smart.community.user.entity.UserPropertyCompany;
import com.smart.community.user.dto.AddPropertyCompanyUserDTO;
import com.smart.community.user.dto.AvatarUploadDTO;
import com.smart.community.user.dto.AvatarUploadResponseDTO;
import com.smart.community.user.dto.LoginDTO;
import com.smart.community.user.dto.UserDTO;
import com.smart.community.user.dto.UserQueryDTO;
import com.smart.community.user.dto.UserProfileUpdateDTO;
import com.smart.community.user.dto.UserByRoleGroupDTO;
import com.smart.community.user.dto.UserSimpleDTO;
import com.smart.community.user.entity.LoginLog;
import com.smart.community.user.entity.User;
import com.smart.community.user.entity.UserRole;
import com.smart.community.user.mapper.UserMapper;
import com.smart.community.user.service.RoleService;
import com.smart.community.user.service.UserPropertyCompanyService;
import com.smart.community.user.service.UserRoleService;
import com.smart.community.user.service.UserService;
import com.smart.community.user.mapper.LoginLogMapper;
import com.smart.community.user.mapper.UserPropertyCompanyMapper;
import com.smart.community.user.vo.UserPropertyCompanyVO;
import com.smart.community.user.vo.UserVO;

import cn.hutool.core.util.StrUtil;

import com.smart.community.user.vo.RoleVO;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import java.io.InputStream;

import io.seata.spring.annotation.GlobalTransactional;

/**
 * 用户服务实现
 *
 * @author Wu.Liang
 * @since 2025-07-05
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private UserPropertyCompanyService userPropertyCompanyService;
    
    @Autowired
    private DataScopeFeign dataScopeFeign;
    
    @Autowired
    private LoginLogMapper loginLogMapper;
    
    @Autowired
    private UserPropertyCompanyMapper userPropertyCompanyMapper;
    
    @Autowired
    private MinioClient minioClient;
    
    @org.springframework.beans.factory.annotation.Value("${minio.bucket-name:smart-community}")
    private String bucketName;
    
    @org.springframework.beans.factory.annotation.Value("${minio.endpoint:http://localhost:9000}")
    private String endpoint;

    // ==================== 缓存优化说明 ====================
    // 已移除手动Redis缓存操作，统一使用Spring Cache注解
    // 所有缓存操作通过@Cacheable、@CacheEvict注解自动管理
    // 遵循《Java后端SpringBoot代码开发规范_重构版.md》缓存规范

    @Override
    public Map<String, Object> login(LoginDTO loginDTO) throws Exception {
        log.info("用户登录请求: username={}", loginDTO.getUsername());
        
        // 1. 验证用户名是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, loginDTO.getUsername());
        User user = this.getOne(queryWrapper);
        
        if (user == null) {
            log.warn("登录失败: 用户名不存在, username={}", loginDTO.getUsername());
            throw new BusinessException("用户名或密码错误");
        }
        
        // 2. 检查用户状态
        if (user.getStatus() == null || user.getStatus() != 1) {
            log.warn("登录失败: 用户状态异常, username={}, status={}", loginDTO.getUsername(), user.getStatus());
            throw new BusinessException("用户已被禁用或锁定");
        }
        
        // 3. 验证密码
        String encryptedPassword = SecurityUtils.encryptPassword(loginDTO.getPassword());
        if (!encryptedPassword.equals(user.getPassword())) {
            log.warn("登录失败: 密码错误, username={}", loginDTO.getUsername());
            throw new BusinessException("用户名或密码错误");
        }
        
        // 4. 获取用户角色和权限
        List<Map<String, Object>> roles = getUserRoles(user.getId());
        List<Map<String, Object>> menus = getUserMenus(user.getId());
        
        // 5. 使用Sa-Token登录
        SecurityUtils.login(user.getId());
        String token = SecurityUtils.getTokenValue();
        
        // 6. 记录登录日志
        try {
            LoginLog loginLog = new LoginLog();
            loginLog.setUserId(user.getId());
            loginLog.setUsername(user.getUsername());
            loginLog.setLoginTime(LocalDateTime.now());
            loginLog.setLoginIp("127.0.0.1"); // 暂时使用默认IP，后续可从请求中获取真实IP
            loginLog.setLoginAddress("未知");
            loginLog.setBrowser("未知");
            loginLog.setOs("未知");
            loginLog.setLoginStatus(0); // 0表示成功
            loginLog.setLoginMessage("登录成功");
            loginLog.setStatus(1);
            loginLogMapper.insert(loginLog);
        } catch (Exception e) {
            log.warn("记录登录日志失败: {}", e.getMessage());
        }
        
        // 7. 构建返回数据
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("user", convertToUserVO(user));
        result.put("roles", roles);
        result.put("menus", menus);
        
        log.info("用户登录成功: username={}, userId={}", user.getUsername(), user.getId());
        return result;
    }

    @Override
    public void logout(Long userId) throws Exception {
        log.info("用户登出请求: userId={}", userId);
        
        try {
            // 1. 使用Sa-Token登出
            SecurityUtils.logout();
            
            // 2. 记录登出日志
            LoginLog loginLog = new LoginLog();
            loginLog.setUserId(userId);
            loginLog.setLogoutTime(LocalDateTime.now());
            loginLog.setLoginStatus(0); // 0表示成功
            loginLog.setLoginMessage("登出成功");
            loginLog.setStatus(1);
            loginLogMapper.insert(loginLog);
            
            log.info("用户登出成功: userId={}", userId);
        } catch (Exception e) {
            log.error("用户登出失败: userId={}, error={}", userId, e.getMessage());
            throw new BusinessException("登出失败: " + e.getMessage());
        }
    }

    @Override
    @Cacheable(value = "user:page", key = "#queryDTO.current + ':' + #queryDTO.size + ':' + #queryDTO.username + ':' + #queryDTO.realName + ':' + #queryDTO.phone + ':' + #queryDTO.email + ':' + #queryDTO.userType + ':' + #queryDTO.status + ':' + T(com.smart.community.commons.utils.SecurityUtils).getCurrentUserId()", unless = "#result == null || #result.getRecords().isEmpty()")
    public IPage<User> getUserPage(UserQueryDTO queryDTO) throws Exception {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        log.info("用户列表查询开始，当前用户ID：{}，查询条件：{}", currentUserId, queryDTO);
        
        try {
            // 1. 检查超级管理员权限
            Boolean isSuperAdmin = dataScopeFeign.isUserSuperAdmin(currentUserId);
            if (isSuperAdmin != null && isSuperAdmin) {
                log.info("超级管理员权限，查询所有用户数据");
                return getUserPageWithQuery(queryDTO);
            }
            
            // 2. 非超级管理员：根据物业公司数据权限查询
            return getUserPageWithPropertyCompanyPermission(queryDTO, currentUserId);
            
        } catch (Exception e) {
            log.error("用户列表查询失败，当前用户ID：{}，错误：{}", currentUserId, e.getMessage(), e);
            // 返回空分页结果，避免系统异常
            return new Page<>(queryDTO.getCurrent(), queryDTO.getSize(), 0L);
        }
    }
    
    /**
     * 带查询条件的分页查询（无权限限制）
     */
    private IPage<User> getUserPageWithQuery(UserQueryDTO queryDTO) {
        LambdaQueryWrapper<User> queryWrapper = buildQueryWrapper(queryDTO);
        Page<User> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        return this.page(page, queryWrapper);
    }
    
    
    /**
     * 根据物业公司数据权限的分页查询
     * 
     * @param queryDTO 查询条件
     * @param currentUserId 当前用户ID
     * @return 分页结果
     * @throws Exception 统一异常
     */
    private IPage<User> getUserPageWithPropertyCompanyPermission(UserQueryDTO queryDTO, Long currentUserId) throws Exception {
        log.info("根据物业公司数据权限查询用户列表，当前用户ID：{}", currentUserId);
        
        try {
            // 1. 获取用户关联的物业公司IDs
            List<Long> propertyCompanyIds = dataScopeFeign.getUserPropertyCompanyIds(currentUserId);
            if (propertyCompanyIds == null || propertyCompanyIds.isEmpty()) {
                log.warn("用户未关联任何物业公司，返回空结果，用户ID：{}", currentUserId);
                return new Page<>(queryDTO.getCurrent(), queryDTO.getSize(), 0L);
            }
            
            log.info("用户关联的物业公司IDs：{}", propertyCompanyIds);
            
            // 2. 根据物业公司IDs查询用户和物业公司关联表，获取范围内的用户IDs
            List<Long> userIds = dataScopeFeign.getUserIdsByPropertyCompanyIds(propertyCompanyIds);
            if (userIds == null || userIds.isEmpty()) {
                log.warn("物业公司范围内无用户数据，返回空结果，物业公司IDs：{}", propertyCompanyIds);
                return new Page<>(queryDTO.getCurrent(), queryDTO.getSize(), 0L);
            }
            
            log.info("物业公司范围内的用户IDs数量：{}", userIds.size());
            
            // 3. 根据用户IDs查询用户表
            LambdaQueryWrapper<User> queryWrapper = buildQueryWrapper(queryDTO);
            queryWrapper.in(User::getId, userIds);
            
            Page<User> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
            IPage<User> result = this.page(page, queryWrapper);
            
            log.info("根据物业公司数据权限查询用户列表成功，查询结果数量：{}", result.getRecords().size());
            return result;
            
        } catch (Exception e) {
            log.error("根据物业公司数据权限查询用户列表失败，当前用户ID：{}，错误：{}", currentUserId, e.getMessage(), e);
            // 返回空分页结果，避免系统异常
            return new Page<>(queryDTO.getCurrent(), queryDTO.getSize(), 0L);
        }
    }
    
    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<User> buildQueryWrapper(UserQueryDTO queryDTO) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        
        if (queryDTO.getUsername() != null && !queryDTO.getUsername().isEmpty()) {
            queryWrapper.like(User::getUsername, queryDTO.getUsername());
        }
        if (queryDTO.getRealName() != null && !queryDTO.getRealName().isEmpty()) {
            queryWrapper.like(User::getRealName, queryDTO.getRealName());
        }
        if (queryDTO.getPhone() != null && !queryDTO.getPhone().isEmpty()) {
            queryWrapper.like(User::getPhone, queryDTO.getPhone());
        }
        if (queryDTO.getEmail() != null && !queryDTO.getEmail().isEmpty()) {
            queryWrapper.like(User::getEmail, queryDTO.getEmail());
        }
        if (queryDTO.getUserType() != null) {
            queryWrapper.eq(User::getUserType, queryDTO.getUserType());
        }
        if (queryDTO.getStatus() != null) {
            queryWrapper.eq(User::getStatus, queryDTO.getStatus());
        }
        
        return queryWrapper;
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void createUser(UserDTO userDTO) throws Exception {
        // 检查身份证号重复
        if (userDTO.getIdCard() != null && !userDTO.getIdCard().trim().isEmpty()) {
            if (!checkIdCardUnique(userDTO.getIdCard().trim(), null)) {
                throw new BusinessException("身份证号重复");
            }
        }
        
        // 检查手机号重复
        if (userDTO.getPhone() != null && !userDTO.getPhone().trim().isEmpty()) {
            if (!checkPhoneUnique(userDTO.getPhone().trim(), null)) {
                throw new BusinessException("手机号重复");
            }
        }
        
        // 设置默认值
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        if (user.getStatus() == null) {
            user.setStatus(1); // 默认启用
        }
        
        // 密码加密
        if (user.getPassword() != null && !user.getPassword().isEmpty()) {
            user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        }
        
        this.save(user);
        
        // 缓存清理已通过@CacheEvict注解自动处理
        log.debug("用户创建成功，用户ID：{}", user.getId());
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void updateUser(UserDTO userDTO) throws Exception {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        
        // 1. 检查超级管理员权限
        Boolean isSuperAdmin = dataScopeFeign.isUserSuperAdmin(currentUserId);
        if (!isSuperAdmin) {
            // 2. 获取目标用户信息
            User targetUser = this.getById(userDTO.getId());
            if (targetUser == null) {
                throw new BusinessException("用户不存在");
            }
            
            // 3. 验证操作权限
            Boolean hasPermission = dataScopeFeign.hasPropertyCompanyPermission(
                currentUserId, targetUser.getPropertyCompanyId());
            
            if (!hasPermission) {
                throw new BusinessException("无权限操作该用户");
            }
        }
        
        // 检查身份证号重复
        if (userDTO.getIdCard() != null && !userDTO.getIdCard().trim().isEmpty()) {
            if (!checkIdCardUnique(userDTO.getIdCard().trim(), userDTO.getId())) {
                throw new BusinessException("身份证号重复");
            }
        }
        
        // 检查手机号重复
        if (userDTO.getPhone() != null && !userDTO.getPhone().trim().isEmpty()) {
            if (!checkPhoneUnique(userDTO.getPhone().trim(), userDTO.getId())) {
                throw new BusinessException("手机号重复");
            }
        }
        
        // 查询现有用户，保留版本号以确保乐观锁正常工作
        User existingUser = this.getById(userDTO.getId());
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }
        
        BeanUtils.copyProperties(userDTO, existingUser);
        existingUser.setUpdateTime(LocalDateTime.now());
        this.updateById(existingUser);
        
        // 缓存清理已通过@CacheEvict注解自动处理
        log.debug("用户更新成功，用户ID：{}", existingUser.getId());
    }

    @Override
    @GlobalTransactional
    public UserVO updateUserProfile(Long userId, UserProfileUpdateDTO updateDTO) throws Exception {
        // 获取用户信息
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 检查手机号重复（排除当前用户）- 只有当手机号发生变化时才检查
        if (updateDTO.getPhone() != null && !updateDTO.getPhone().trim().isEmpty()) {
            String currentPhone = user.getPhone();
            String newPhone = updateDTO.getPhone().trim();
            // 只有当手机号真正发生变化时才进行重复性检查
            if (!newPhone.equals(currentPhone)) {
                if (!checkPhoneUnique(newPhone, userId)) {
                    throw new BusinessException("手机号重复");
                }
            }
        }
        
        // 检查邮箱重复（排除当前用户）- 只有当邮箱发生变化时才检查
        if (updateDTO.getEmail() != null && !updateDTO.getEmail().trim().isEmpty()) {
            String currentEmail = user.getEmail();
            String newEmail = updateDTO.getEmail().trim();
            // 只有当邮箱真正发生变化时才进行重复性检查
            if (!newEmail.equals(currentEmail)) {
                if (!checkEmailUnique(newEmail, userId)) {
                    throw new BusinessException("邮箱重复");
                }
            }
        }
        
        // 更新用户信息
        User updateUser = new User();
        updateUser.setId(userId);
        updateUser.setRealName(updateDTO.getRealName());
        // 昵称字段：如果提供了值就更新，包括空字符串
        if (updateDTO.getNickname() != null) {
            updateUser.setNickname(updateDTO.getNickname());
        } else {
            // 如果nickname为null，设置为空字符串
            updateUser.setNickname("");
        }
        updateUser.setPhone(updateDTO.getPhone());
        updateUser.setEmail(updateDTO.getEmail());
        updateUser.setAvatar(updateDTO.getAvatar());
        updateUser.setUpdateTime(LocalDateTime.now());
        updateUser.setUpdateBy(userId);
        
        // 保存更新
        boolean success = this.updateById(updateUser);
        if (!success) {
            throw new BusinessException("更新失败");
        }
        
        // 缓存清理已通过@CacheEvict注解自动处理
        
        // 返回更新后的用户信息
        User updatedUser = this.getById(userId);
        UserVO userVO = new UserVO();
        
        // 明确复制所有字段，确保nickname字段正确复制
        userVO.setId(updatedUser.getId());
        userVO.setUsername(updatedUser.getUsername());
        userVO.setNickname(updatedUser.getNickname());
        userVO.setRealName(updatedUser.getRealName());
        userVO.setPhone(updatedUser.getPhone());
        userVO.setEmail(updatedUser.getEmail());
        userVO.setAvatar(updatedUser.getAvatar());
        userVO.setUserType(updatedUser.getUserType());
        userVO.setStatus(updatedUser.getStatus());
        userVO.setCreateTime(updatedUser.getCreateTime());
        userVO.setUpdateTime(updatedUser.getUpdateTime());
        userVO.setLastLoginTime(updatedUser.getLastLoginTime());
        userVO.setLastLoginIp(updatedUser.getLastLoginIp());
        
        return userVO;
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void deleteUser(Long userId) throws Exception {
        Long currentUserId = SecurityUtils.getCurrentUserId();
        
        // 1. 检查超级管理员权限
        Boolean isSuperAdmin = dataScopeFeign.isUserSuperAdmin(currentUserId);
        if (!isSuperAdmin) {
            // 2. 获取目标用户信息
            User targetUser = this.getById(userId);
            if (targetUser == null) {
                throw new BusinessException("用户不存在");
            }
            
            // 3. 验证操作权限
            Boolean hasPermission = dataScopeFeign.hasPropertyCompanyPermission(
                currentUserId, targetUser.getPropertyCompanyId());
            
            if (!hasPermission) {
                throw new BusinessException("无权限删除该用户");
            }
        }
        
        // 删除用户角色关联
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, userId);
        userRoleService.remove(queryWrapper);
        // 删除用户
        this.removeById(userId);
        
        // 缓存清理已通过@CacheEvict注解自动处理
        log.debug("用户删除成功，用户ID：{}", userId);
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void batchDeleteUsers(List<Long> userIds) throws Exception {
        // 批量删除用户角色关联
        for (Long userId : userIds) {
            LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserRole::getUserId, userId);
            userRoleService.remove(queryWrapper);
        }
        // 批量删除用户
        this.removeByIds(userIds);
        
        // 缓存清理已通过@CacheEvict注解自动处理
        log.debug("批量删除用户成功，用户ID列表：{}", userIds);
    }

    @Override
    @GlobalTransactional
    public void resetPassword(Long userId, String newPassword) throws Exception {
        // 查询现有用户，保留版本号以确保乐观锁正常工作
        User existingUser = this.getById(userId);
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }
        
        existingUser.setPassword(SecurityUtils.encryptPassword(newPassword));
        existingUser.setUpdateTime(LocalDateTime.now());
        this.updateById(existingUser);
    }

    @Override
    @GlobalTransactional
    public void changePassword(Long userId, String oldPassword, String newPassword) throws Exception {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        
        // 验证旧密码
        if (!SecurityUtils.verifyPassword(oldPassword, user.getPassword())) {
            throw new BusinessException("旧密码不正确");
        }
        
        // 更新密码
        user.setPassword(SecurityUtils.encryptPassword(newPassword));
        user.setUpdateTime(LocalDateTime.now());
        this.updateById(user);
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void enableUser(Long userId) throws Exception {
        updateUserStatus(userId, 1);
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void disableUser(Long userId) throws Exception {
        updateUserStatus(userId, 0);
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void lockUser(Long userId) throws Exception {
        updateUserStatus(userId, 2);
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void unlockUser(Long userId) throws Exception {
        updateUserStatus(userId, 1);
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void assignRoles(Long userId, List<Long> roleIds) throws Exception {
        if (userId == null || roleIds == null || roleIds.isEmpty()) {
            throw new IllegalArgumentException("用户ID和角色ID列表不能为空");
        }
        
        // 检查每个角色是否已经存在，只添加不存在的角色
        List<Long> newRoleIds = new ArrayList<>();
        for (Long roleId : roleIds) {
            if (!userRoleService.userHasRole(userId, roleId)) {
                newRoleIds.add(roleId);
            } else {
                log.info("用户已拥有角色，跳过分配，用户ID：{}，角色ID：{}", userId, roleId);
            }
        }
        
        // 只添加新的角色关联
        if (!newRoleIds.isEmpty()) {
            userRoleService.assignRolesToUser(userId, newRoleIds);
            log.info("用户角色新增成功，用户ID：{}，新增角色ID：{}", userId, newRoleIds);
        } else {
            log.info("用户已拥有所有指定角色，无需新增，用户ID：{}，角色ID：{}", userId, roleIds);
        }
        
        // 缓存清理已通过@CacheEvict注解自动处理
        log.debug("用户角色分配成功，用户ID：{}", userId);
    }
    
    // 权限缓存清理已通过@CacheEvict注解自动处理

    @Override
    @Cacheable(value = "user:roles", key = "#userId", unless = "#result == null || #result.isEmpty()")
    public List<Map<String, Object>> getUserRoles(Long userId) throws Exception {
        if (userId == null) {
            return new ArrayList<>();
        }
        
        // 从数据库查询用户角色
        List<UserRole> userRoles = userRoleService.getUserRolesByUserId(userId);
        List<Map<String, Object>> result = new ArrayList<>();
        for (UserRole userRole : userRoles) {
            Map<String, Object> roleMap = new HashMap<>();
            roleMap.put("roleId", userRole.getRoleId());
            roleMap.put("userId", userRole.getUserId());
            result.add(roleMap);
        }
        
        return result;
    }

    @Override
    public List<Map<String, Object>> getUserMenus(Long userId) throws Exception {
        // 临时实现，返回空列表
        return new ArrayList<>();
    }

    @Override
    @Cacheable(value = "user:unique:check", key = "'username:' + #username + ':' + (#userId != null ? #userId : 'null')", unless = "#result == null")
    public boolean checkUsernameUnique(String username, Long userId) throws Exception {
        if (username == null || username.trim().isEmpty()) {
            return true;
        }
        
        String usernameTrim = username.trim();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, usernameTrim);
        if (userId != null) {
            queryWrapper.ne(User::getId, userId);
        }
        return this.count(queryWrapper) == 0;
    }

    @Override
    @Cacheable(value = "user:unique:check", key = "'phone:' + #phone + ':' + (#userId != null ? #userId : 'null')", unless = "#result == null")
    public boolean checkPhoneUnique(String phone, Long userId) throws Exception {
        if (phone == null || phone.trim().isEmpty()) {
            return true;
        }
        
        String phoneTrim = phone.trim();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phoneTrim);
        if (userId != null) {
            queryWrapper.ne(User::getId, userId);
        }
        return this.count(queryWrapper) == 0;
    }

    @Override
    @Cacheable(value = "user:unique:check", key = "'email:' + #email + ':' + (#userId != null ? #userId : 'null')", unless = "#result == null")
    public boolean checkEmailUnique(String email, Long userId) throws Exception {
        if (email == null || email.trim().isEmpty()) {
            return true;
        }
        
        String emailTrim = email.trim();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, emailTrim);
        if (userId != null) {
            queryWrapper.ne(User::getId, userId);
        }
        return this.count(queryWrapper) == 0;
    }

    @Override
    @Cacheable(value = "user:unique:check", key = "'idcard:' + #idCard + ':' + (#userId != null ? #userId : 'null')", unless = "#result == null")
    public boolean checkIdCardUnique(String idCard, Long userId) throws Exception {
        if (idCard == null || idCard.trim().isEmpty()) {
            return true;
        }
        
        String idCardTrim = idCard.trim();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getIdCard, idCardTrim);
        if (userId != null) {
            queryWrapper.ne(User::getId, userId);
        }
        return this.count(queryWrapper) == 0;
    }

    @Override
    public boolean checkUsernameExists(String username) throws Exception {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        return this.count(queryWrapper) > 0;
    }

    @Override
    public boolean checkPhoneExists(String phone) throws Exception {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phone);
        return this.count(queryWrapper) > 0;
    }

    @Override
    public boolean checkEmailExists(String email) throws Exception {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, email);
        return this.count(queryWrapper) > 0;
    }

    @Override
    @GlobalTransactional
    public void updateUserStatus(Long userId, Integer status) throws Exception {
        // 查询现有用户，保留版本号以确保乐观锁正常工作
        User existingUser = this.getById(userId);
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }
        
        existingUser.setStatus(status);
        existingUser.setUpdateTime(LocalDateTime.now());
        this.updateById(existingUser);
    }

    @Override
    public com.smart.community.user.vo.UserRoleAssignVO getUserRoleAssignInfo(Long userId) throws Exception {
        com.smart.community.user.vo.UserRoleAssignVO vo = new com.smart.community.user.vo.UserRoleAssignVO();
        User user = this.getById(userId);
        if (user == null) {
            return vo;
        }
        vo.setUserId(user.getId());
        vo.setUsername(user.getUsername());
        vo.setRealName(user.getRealName());
        vo.setPhone(user.getPhone());
        vo.setEmail(user.getEmail());
        // 当前角色ID列表
        List<com.smart.community.user.entity.UserRole> userRoles = userRoleService.getUserRolesByUserId(userId);
        List<Long> currentRoleIds = new ArrayList<>();
        List<String> currentRoleNames = new ArrayList<>();
        if (userRoles != null) {
            for (com.smart.community.user.entity.UserRole ur : userRoles) {
                if (ur != null && ur.getRoleId() != null) {
                    currentRoleIds.add(ur.getRoleId());
                    // 查询角色名称
                    com.smart.community.user.vo.RoleVO roleVO = roleService.getRole(ur.getRoleId());
                    if (roleVO != null && roleVO.getRoleName() != null) {
                        currentRoleNames.add(roleVO.getRoleName());
                    }
                }
            }
        }
        vo.setCurrentRoleIds(currentRoleIds);
        vo.setCurrentRoleNames(currentRoleNames);
        // 可用角色列表
        List<com.smart.community.user.vo.RoleVO> availableRoles = new ArrayList<>();
        try {
            com.smart.community.user.dto.RoleQueryDTO roleQueryDTO = new com.smart.community.user.dto.RoleQueryDTO();
            roleQueryDTO.setCurrent(1);
            roleQueryDTO.setSize(1000); // 设置较大的页面大小以获取所有角色
            com.smart.community.user.vo.PageResult<com.smart.community.user.vo.RoleVO> rolePageResult = roleService.getRoleList(roleQueryDTO);
            if (rolePageResult != null && rolePageResult.getRecords() != null) {
                // 过滤掉"管理员"和"超级管理员"角色
                availableRoles = rolePageResult.getRecords().stream()
                    .filter(role -> {
                        String roleName = role.getRoleName();
                        return roleName != null && 
                               !roleName.equals("管理员") && 
                               !roleName.equals("超级管理员");
                    })
                    .collect(java.util.stream.Collectors.toList());
            }
        } catch (Exception e) {
            // 记录错误但不影响主流程
            log.warn("获取可用角色列表失败", e);
        }
        vo.setAvailableRoles(availableRoles);
        return vo;
    }

    /**
     * 将User实体转换为UserVO
     * 
     * @param user 用户实体
     * @return 用户VO
     */
    private UserVO convertToUserVO(User user) {
        if (user == null) {
            return null;
        }
        
        UserVO userVO = new UserVO();
        userVO.setId(user.getId());
        userVO.setUsername(user.getUsername());
        userVO.setRealName(user.getRealName());
        userVO.setEmail(user.getEmail());
        userVO.setPhone(user.getPhone());
        userVO.setUserType(user.getUserType());
        userVO.setStatus(user.getStatus());
        userVO.setCreateTime(user.getCreateTime());
        
        return userVO;
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group", "userPropertyCompany", "user:property:companies", "user:company:ids", "property:company:users"}, allEntries = true)
    public void addPropertyCompanyUser(AddPropertyCompanyUserDTO addPropertyCompanyUserDTO) throws Exception {
        log.info("新增物业公司用户，用户数据：{}", addPropertyCompanyUserDTO);
        
        // 获取当前用户ID
        Long currentUserId = SecurityUtils.getCurrentUserId();
        if (currentUserId == null) {
            log.warn("获取当前用户ID失败，新增物业公司用户失败");
            throw new BusinessException("获取当前用户ID失败");
        }
        
        // 根据手机号查询用户
        String phone = addPropertyCompanyUserDTO.getPhone().trim();
        User existingUser = this.getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
        
        if (existingUser != null) {
            // 更新用户信息
            existingUser.setRealName(addPropertyCompanyUserDTO.getRealName());
            existingUser.setEmail(addPropertyCompanyUserDTO.getEmail());
            if (StrUtil.isBlankIfStr(existingUser.getUserType())) {
            	existingUser.setUserType(addPropertyCompanyUserDTO.getUserType());
            }
            existingUser.setPropertyCompanyId(addPropertyCompanyUserDTO.getPropertyCompanyId());
            existingUser.setUpdateTime(LocalDateTime.now());
            existingUser.setUpdateBy(currentUserId);
            
            // 更新用户
            this.updateById(existingUser);
            
            // 使用统一的角色分配方法
            boolean roleAssigned = assignUserRole(
                existingUser.getId(),
                addPropertyCompanyUserDTO.getPosition(),
                addPropertyCompanyUserDTO.getUserType(),
                addPropertyCompanyUserDTO.getRoleId()
            );
            
            if (!roleAssigned) {
                log.warn("角色分配失败，用户ID：{}，职位：{}，用户类型：{}，指定角色ID：{}", 
                        existingUser.getId(), addPropertyCompanyUserDTO.getPosition(), 
                        addPropertyCompanyUserDTO.getUserType(), addPropertyCompanyUserDTO.getRoleId());
            }
            
            // 关联物业公司（完整信息）
            userPropertyCompanyService.associateUserWithCompanyFull(
                existingUser.getId(), 
                addPropertyCompanyUserDTO.getPropertyCompanyId(),
                addPropertyCompanyUserDTO.getPosition(),
                addPropertyCompanyUserDTO.getDepartment(),
                addPropertyCompanyUserDTO.getEmployeeNo(),
                addPropertyCompanyUserDTO.getJoinDate(),
                addPropertyCompanyUserDTO.getRemark()
            );
            
            log.info("更新现有用户成功，用户ID：{}", existingUser.getId());
            return;
        }
        
        // 手机号不存在，创建新用户
		// 检查用户名重复
		String username = addPropertyCompanyUserDTO.getUsername().trim();
		if (!checkUsernameUnique(username, null)) {
			log.warn("用户名重复，用户名：{}", username);
			throw new BusinessException("用户名已存在，请使用其他用户名");
		}
        
        // 1. 创建用户实体
        User user = new User();
        user.setUsername(username);
        user.setRealName(addPropertyCompanyUserDTO.getRealName());
        user.setPhone(phone);
        user.setEmail(addPropertyCompanyUserDTO.getEmail());
        user.setUserType(addPropertyCompanyUserDTO.getUserType());
        user.setStatus(SystemStatusEnum.ENABLED.getCode());
        user.setPropertyCompanyId(addPropertyCompanyUserDTO.getPropertyCompanyId());
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        user.setCreateBy(currentUserId);
        
        // 2. 设置默认密码
        user.setPassword(SecurityUtils.encryptPassword("123456"));
        
        // 3. 保存用户
        this.save(user);
        
        // 4. 使用统一的角色分配方法
        boolean roleAssigned = assignUserRole(
            user.getId(),
            addPropertyCompanyUserDTO.getPosition(),
            addPropertyCompanyUserDTO.getUserType(),
            addPropertyCompanyUserDTO.getRoleId()
        );
        
        if (!roleAssigned) {
            log.warn("新用户角色分配失败，用户ID：{}，职位：{}，用户类型：{}，指定角色ID：{}", 
                    user.getId(), addPropertyCompanyUserDTO.getPosition(), 
                    addPropertyCompanyUserDTO.getUserType(), addPropertyCompanyUserDTO.getRoleId());
        }
        
        // 5. 关联物业公司（完整信息）
        userPropertyCompanyService.associateUserWithCompanyFull(
            user.getId(), 
            addPropertyCompanyUserDTO.getPropertyCompanyId(),
            addPropertyCompanyUserDTO.getPosition(),
            addPropertyCompanyUserDTO.getDepartment(),
            addPropertyCompanyUserDTO.getEmployeeNo(),
            addPropertyCompanyUserDTO.getJoinDate(),
            addPropertyCompanyUserDTO.getRemark()
        );
        
        // 缓存清理已通过@CacheEvict注解自动处理
        log.debug("新增物业公司用户成功，用户ID：{}，物业公司ID：{}", 
                user.getId(), addPropertyCompanyUserDTO.getPropertyCompanyId());
        
        log.info("新增物业公司用户成功，用户ID：{}", user.getId());
    }

    @Override
    @Cacheable(value = "user:property:company", key = "#propertyCompanyId + ':' + #current + ':' + #size", unless = "#result == null || #result.getRecords().isEmpty()")
    public PageResult<UserVO> getPropertyCompanyUsers(Long propertyCompanyId, Integer current, Integer size) throws Exception {
        log.info("获取物业公司用户列表，物业公司ID：{}，当前页：{}，页大小：{}", propertyCompanyId, current, size);
        
        // 缓存未命中，从数据库查询
        // 1. 获取物业公司关联的用户列表
        List<UserPropertyCompanyVO> userPropertyCompanies = userPropertyCompanyService.getPropertyCompanyUsers(propertyCompanyId);
        if (userPropertyCompanies.isEmpty()) {
            PageResult<UserVO> emptyResult = new PageResult<>(current, size, 0L, new ArrayList<>());
            log.debug("物业公司用户列表为空，物业公司ID：{}", propertyCompanyId);
            return emptyResult;
        }
        
        // 提取用户ID列表
        List<Long> userIds = new ArrayList<>();
        for (UserPropertyCompanyVO vo : userPropertyCompanies) {
            if (vo.getUserId() != null) {
                userIds.add(vo.getUserId());
            }
        }
        
        // 2. 分页查询用户信息
        Page<User> page = new Page<>(current, size);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(User::getId, userIds);
        queryWrapper.orderByDesc(User::getUpdateTime);
        
        IPage<User> userPage = this.page(page, queryWrapper);
        
        // 3. 转换为VO
        List<UserVO> userVOList = new ArrayList<>();
        for (User user : userPage.getRecords()) {
            userVOList.add(convertToUserVO(user));
        }
        
        PageResult<UserVO> result = new PageResult<>(current, size, userPage.getTotal(), userVOList);
        log.debug("物业公司用户列表查询完成，物业公司ID：{}，用户数量：{}", propertyCompanyId, result.getRecords().size());
        
        return result;
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void enablePropertyCompanyUser(Long userId) throws Exception {
        log.info("启用物业公司用户，用户ID：{}", userId);
        updateUserStatus(userId, 1);
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void disablePropertyCompanyUser(Long userId) throws Exception {
        log.info("禁用物业公司用户，用户ID：{}", userId);
        updateUserStatus(userId, 0);
    }

    @Override
    @GlobalTransactional
    @CacheEvict(value = {"user:page", "user:list", "user:property:company", "user:statistics", "user:roles", "user:current", "user:unique:check", "user:by:idcard", "user:by:phone", "user:role:group"}, allEntries = true)
    public void resetPropertyCompanyUserPassword(Long userId) throws Exception {
        log.info("重置物业公司用户密码，用户ID：{}", userId);
        resetPassword(userId, "123456");
    }

    @Override
    @Cacheable(value = "user:list", key = "#currentUserId + ':' + (#queryDTO != null ? #queryDTO.username + ':' + #queryDTO.realName + ':' + #queryDTO.phone + ':' + #queryDTO.userType + ':' + #queryDTO.status : 'null')", unless = "#result == null || #result.isEmpty()")
    public List<User> getUsersByDataPermission(Long currentUserId, UserQueryDTO queryDTO) throws Exception {
        log.info("根据数据权限查询用户列表，当前用户ID：{}，查询条件：{}", currentUserId, queryDTO);
        
        try {
            // 获取当前用户的数据权限信息
            DataScopeInfo dataScopeInfo = dataScopeFeign.getUserDataScope(currentUserId);
            log.info("用户数据权限信息：{}", dataScopeInfo);
            
            // 根据数据权限构建查询条件
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            
            // 根据用户权限范围过滤数据
            if (dataScopeInfo.isSuperAdmin()) {
                // 超级管理员：可以查看所有用户
                log.debug("超级管理员权限，查询所有用户");
            } else if (dataScopeInfo.isPropertyCompanyUser()) {
                // 物业公司用户：只能查看本公司用户
                List<Long> propertyCompanyIds = dataScopeInfo.getPropertyCompanyIds();
                if (propertyCompanyIds != null && !propertyCompanyIds.isEmpty()) {
                    queryWrapper.in(User::getPropertyCompanyId, propertyCompanyIds);
                    log.debug("物业公司用户权限，查询物业公司ID：{}", propertyCompanyIds);
                }
            } else if (dataScopeInfo.isOwnerUser()) {
                // 业主用户：只能查看关联社区的用户
                List<Long> communityIds = dataScopeInfo.getCommunityIds();
                if (communityIds != null && !communityIds.isEmpty()) {
                    queryWrapper.in(User::getCommunityId, communityIds);
                    log.debug("业主用户权限，查询社区ID：{}", communityIds);
                }
            } else {
                // 普通用户：只能查看自己的信息
                queryWrapper.eq(User::getId, currentUserId);
                log.debug("普通用户权限，只能查看自己的信息");
            }
            
            // 添加查询条件
            if (queryDTO != null) {
                if (queryDTO.getUsername() != null && !queryDTO.getUsername().trim().isEmpty()) {
                    queryWrapper.like(User::getUsername, queryDTO.getUsername().trim());
                }
                if (queryDTO.getRealName() != null && !queryDTO.getRealName().trim().isEmpty()) {
                    queryWrapper.like(User::getRealName, queryDTO.getRealName().trim());
                }
                if (queryDTO.getPhone() != null && !queryDTO.getPhone().trim().isEmpty()) {
                    queryWrapper.like(User::getPhone, queryDTO.getPhone().trim());
                }
                if (queryDTO.getUserType() != null) {
                    queryWrapper.eq(User::getUserType, queryDTO.getUserType());
                }
                if (queryDTO.getStatus() != null) {
                    queryWrapper.eq(User::getStatus, queryDTO.getStatus());
                }
            }
            
            // 只查询启用状态的用户
            queryWrapper.eq(User::getStatus, SystemStatusEnum.ENABLED.getCode());
            
            // 执行查询
            List<User> users = this.list(queryWrapper);
            log.info("根据数据权限查询用户列表成功，当前用户ID：{}，查询结果数量：{}", currentUserId, users.size());
            
            return users;
        } catch (Exception e) {
            log.warn("根据数据权限查询用户列表失败，当前用户ID：{}", currentUserId, e);
            return new ArrayList<>();
        }
    }

    @Override
    @Cacheable(value = "user:by:idcard", key = "#idCard", unless = "#result == null")
    public User getUserByIdCard(String idCard) throws Exception {
        if (idCard == null || idCard.trim().isEmpty()) {
            return null;
        }
        
        String idCardTrim = idCard.trim();
        return baseMapper.selectByIdCard(idCardTrim);
    }

    @Override
    @Cacheable(value = "user:by:phone", key = "#phone", unless = "#result == null")
    public User getUserByPhone(String phone) throws Exception {
        if (phone == null || phone.trim().isEmpty()) {
            log.warn("手机号为空，无法查询用户");
            return null;
        }
        
        String phoneTrim = phone.trim();
        User user = baseMapper.selectByPhone(phoneTrim);
        
        if (user != null) {
            log.debug("根据手机号查询用户成功，手机号：{}，用户ID：{}", phoneTrim, user.getId());
        } else {
            log.debug("根据手机号未找到用户，手机号：{}", phoneTrim);
        }
        return user;
    }

    @Override
    @GlobalTransactional
    public Long createNormalUser(com.smart.community.feign.user.dto.NormalUserCreateDTO dto) throws Exception {
        try {
            // 1. 基本校验与唯一性检查
            if (dto.getPhone() != null && !dto.getPhone().trim().isEmpty()) {
                if (!checkPhoneUnique(dto.getPhone().trim(), null)) {
                    throw new BusinessException("手机号重复");
                }
            }
            if (dto.getIdCard() != null && !dto.getIdCard().trim().isEmpty()) {
                if (!checkIdCardUnique(dto.getIdCard().trim(), null)) {
                    throw new BusinessException("身份证号重复");
                }
            }

            // 2. 组装User实体
            User user = new User();
            user.setUsername(dto.getUsername());
            user.setRealName(dto.getRealName());
            user.setPhone(dto.getPhone());
            user.setEmail(dto.getEmail());
            user.setIdCard(dto.getIdCard());
            user.setGender(dto.getGender());
            user.setBirthday(dto.getBirthday());

            // 3. 用户类型与状态按权威标准设置
            user.setUserType(RoleCodeEnum.NORMAL_USER.getCode());
            user.setStatus(com.smart.community.commons.enums.SystemStatusEnum.ENABLED.getCode());
            user.setAuditStatus(com.smart.community.commons.enums.SystemStatusEnum.AUDIT_APPROVED.getCode());
            user.setIsAdminProtected(0);

            // 4. 密码加密（若未显式提供，则默认123456）
            String rawPwd = (dto.getPassword() != null && !dto.getPassword().isEmpty()) ? dto.getPassword() : "123456";
            user.setPassword(SecurityUtils.encryptPassword(rawPwd));

            // 5. 创建信息：Feign接口禁止从上下文取用户，使用显式传入的operatorId
            if (dto.getOperatorId() != null) {
                user.setCreateBy(dto.getOperatorId());
                user.setUpdateBy(dto.getOperatorId());
            }

            // 6. 持久化
            boolean saved = this.save(user);
            if (!saved) {
                throw new BusinessException("保存用户失败");
            }

            // 7. 分配NORMAL_USER角色
            List<Long> roleIds = new ArrayList<>();
            roleIds.add(13L);
            userRoleService.assignRolesToUser(user.getId(), roleIds);

            log.info("创建普通用户成功，用户ID：{}", user.getId());
            return user.getId();
        } catch (Exception e) {
            log.error("创建普通用户失败", e);
            throw new Exception("创建普通用户失败：" + e.getMessage());
        }
    }

    /**
     * 根据用户类型获取对应的角色ID
     * 
     * @param userType 用户类型
     * @return 角色ID
     */
    private Long getUserTypeRoleId(String userType) {
        switch (userType) {
            case "COMMUNITY_ADMIN": return 3L;
            case "PROPERTY_STAFF": return 4L;
            case "SECURITY_STAFF": return 5L;
            case "REPAIR_STAFF": return 6L;
            case "RESIDENT": return 7L;
            case "PROPERTY_ADMIN": return 9L;
            case "BUILDING_ADMIN": return 10L;
            case "UNIT_ADMIN": return 11L;
            case "HOUSEHOLD_ADMIN": return 12L;
            case "NORMAL_USER": return 13L;
            case "OWNER": return 15L;
            case "SECURITY_ADMIN": return 16L;
            case "CLEANING_STAFF": return 17L;
            case "CLEANING_ADMIN": return 18L;
            case "PARKING_STAFF": return 19L;
            case "PARKING_ADMIN": return 20L;
            default: return null;
        }
    }

    /**
     * 根据职位获取对应的角色ID
     * 
     * @param position 职位
     * @return 角色ID
     */
    private Long getPositionRoleId(String position) {
        if (position == null || position.trim().isEmpty()) {
            return null;
        }
        
        String pos = position.trim();
        switch (pos) {
            case "保洁人员":
                return 17L; // CLEANING_STAFF
            case "保洁管理":
            case "保洁主管":
                return 18L; // CLEANING_ADMIN
            case "安保人员":
                return 5L; // SECURITY_STAFF
            case "安保管理":
            case "安保主管":
                return 16L; // SECURITY_ADMIN
            case "维修人员":
                return 6L; // REPAIR_STAFF
            case "物业人员":
                return 4L; // PROPERTY_STAFF
            case "物业管理员":
            case "物业主管":
                return 9L; // PROPERTY_ADMIN
            case "停车人员":
                return 19L; // PARKING_STAFF
            case "停车管理":
            case "停车主管":
                return 20L; // PARKING_ADMIN
            default:
                return null;
        }
    }

    /**
     * 统一的角色分配方法
     * 根据用户ID、职位、用户类型、指定角色ID等参数，智能分配角色
     * 
     * @param userId 用户ID
     * @param position 职位
     * @param userType 用户类型
     * @param specifiedRoleId 指定的角色ID
     * @return 是否成功分配角色
     */
    private boolean assignUserRole(Long userId, String position, String userType, Long specifiedRoleId) {
        if (userId == null) {
            log.warn("用户ID为空，无法分配角色");
            return false;
        }

        List<Long> roleIdsToAssign = new ArrayList<>();
        
        // 1. 优先使用指定的角色ID
        if (specifiedRoleId != null) {
            try {
                RoleVO role = roleService.getRole(specifiedRoleId);
                if (role != null && role.getStatus() != null && role.getStatus() == 1) {
                    roleIdsToAssign.add(specifiedRoleId);
                    log.info("使用指定角色ID：{}，角色名称：{}", specifiedRoleId, role.getRoleName());
                } else {
                    log.warn("指定的角色不存在或已禁用，角色ID：{}", specifiedRoleId);
                }
            } catch (Exception e) {
                log.error("获取指定角色信息失败，角色ID：{}，错误：{}", specifiedRoleId, e.getMessage());
            }
        }
        
        // 2. 根据职位获取角色ID
        if (roleIdsToAssign.isEmpty()) {
            Long positionRoleId = getPositionRoleId(position);
            if (positionRoleId != null) {
                roleIdsToAssign.add(positionRoleId);
                log.info("根据职位分配角色，职位：{}，角色ID：{}", position, positionRoleId);
            }
        }
        
        // 3. 根据用户类型获取角色ID
        if (roleIdsToAssign.isEmpty()) {
            Long userTypeRoleId = getUserTypeRoleId(userType);
            if (userTypeRoleId != null) {
                roleIdsToAssign.add(userTypeRoleId);
                log.info("根据用户类型分配角色，用户类型：{}，角色ID：{}", userType, userTypeRoleId);
            }
        }
        
        // 4. 如果仍然没有找到角色，记录警告
        if (roleIdsToAssign.isEmpty()) {
            log.warn("无法确定用户角色，用户ID：{}，职位：{}，用户类型：{}，指定角色ID：{}", 
                    userId, position, userType, specifiedRoleId);
            return false;
        }
        
        // 5. 分配角色
        boolean success = true;
        for (Long roleId : roleIdsToAssign) {
            try {
                // 检查用户是否已经拥有该角色
                boolean hasRole = userRoleService.count(new LambdaQueryWrapper<UserRole>()
                    .eq(UserRole::getUserId, userId)
                    .eq(UserRole::getRoleId, roleId)) > 0;
                
                if (!hasRole) {
                    // 添加角色关联
                    UserRole userRole = new UserRole();
                    userRole.setUserId(userId);
                    userRole.setRoleId(roleId);
                    userRoleService.save(userRole);
                    log.info("成功为用户分配角色，用户ID：{}，角色ID：{}", userId, roleId);
                } else {
                    log.info("用户已拥有该角色，用户ID：{}，角色ID：{}", userId, roleId);
                }
            } catch (Exception e) {
                log.error("分配角色失败，用户ID：{}，角色ID：{}，错误：{}", userId, roleId, e.getMessage(), e);
                success = false;
            }
        }
        
        return success;
    }

    @Override
    public List<User> getUsersByRoleCode(String roleCode) throws Exception {
        log.info("根据角色编码获取用户列表，角色编码：{}", roleCode);
        
        // 根据角色编码获取角色ID
        Long roleId = roleService.getRoleIdByCode(roleCode);
        if (roleId == null) {
            log.warn("角色编码不存在，角色编码：{}", roleCode);
            return new ArrayList<>();
        }
        
        // 根据角色ID获取用户列表
        return userRoleService.getUsersByRoleId(roleId);
    }
    
    // ==================== 用户统计方法实现 ====================
    
    @Override
    public Long countUsersByCommunityIds(List<Long> communityIds) throws Exception {
        log.info("根据社区ID列表统计用户数量，社区ID列表：{}", communityIds);
        
        try {
            if (communityIds == null || communityIds.isEmpty()) {
                return 0L;
            }
            
            // 这里需要根据实际的数据库表结构来实现
            // 假设用户表中有community_id字段，或者通过关联表查询
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(User::getCommunityId, communityIds);
            queryWrapper.eq(User::getStatus, SystemStatusEnum.ENABLED.getCode());
            
            long count = this.count(queryWrapper);
            log.info("根据社区ID列表统计用户数量成功，社区ID列表：{}，用户数量：{}", communityIds, count);
            return count;
        } catch (Exception e) {
            log.warn("根据社区ID列表统计用户数量失败，社区ID列表：{}", communityIds, e);
            return 0L;
        }
    }
    
    @Override
    public Long countUsersByPropertyCompanyIds(List<Long> propertyCompanyIds) throws Exception {
        log.info("根据物业公司ID列表统计用户数量，物业公司ID列表：{}", propertyCompanyIds);
        
        try {
            if (propertyCompanyIds == null || propertyCompanyIds.isEmpty()) {
                return 0L;
            }
            
            // 通过用户物业公司关联表查询
            // 查询用户物业公司关联表中，指定物业公司ID列表下的用户数量
            LambdaQueryWrapper<UserPropertyCompany> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(UserPropertyCompany::getPropertyCompanyId, propertyCompanyIds);
            queryWrapper.eq(UserPropertyCompany::getStatus, 1); // 1-在职状态
            
            // 使用UserPropertyCompanyMapper的count方法（BaseMapper提供的方法）
            long count = userPropertyCompanyMapper.selectCount(queryWrapper);
            log.info("根据物业公司ID列表统计用户数量成功，物业公司ID列表：{}，用户数量：{}", propertyCompanyIds, count);
            return count;
        } catch (Exception e) {
            log.warn("根据物业公司ID列表统计用户数量失败，物业公司ID列表：{}", propertyCompanyIds, e);
            return 0L;
        }
    }
    
    @Override
    public Long countUsersByHouseholdIds(List<Long> householdIds) throws Exception {
        log.info("根据房户ID列表统计用户数量，房户ID列表：{}", householdIds);
        
        try {
            if (householdIds == null || householdIds.isEmpty()) {
                return 0L;
            }
            
            // 这里需要根据实际的数据库表结构来实现
            // 假设用户表中有household_id字段，或者通过关联表查询
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(User::getHouseholdId, householdIds);
            queryWrapper.eq(User::getStatus, SystemStatusEnum.ENABLED.getCode());
            
            long count = this.count(queryWrapper);
            log.info("根据房户ID列表统计用户数量成功，房户ID列表：{}，用户数量：{}", householdIds, count);
            return count;
        } catch (Exception e) {
            log.warn("根据房户ID列表统计用户数量失败，房户ID列表：{}", householdIds, e);
            return 0L;
        }
    }
    
    @Override
    public List<Integer> getUserRegistrationTrend(List<Long> communityIds, int months) throws Exception {
        log.info("获取用户注册趋势数据，社区ID列表：{}，统计月份数：{}", communityIds, months);
        
        try {
            if (communityIds == null || communityIds.isEmpty()) {
                return generateEmptyDataList(months);
            }
            
            // 这里需要根据实际的数据库表结构来实现
            // 暂时返回模拟数据
            List<Integer> trendData = new ArrayList<>();
            for (int i = 0; i < months; i++) {
                trendData.add((int) (Math.random() * 100 + 50)); // 模拟50-150之间的随机数
            }
            
            log.info("获取用户注册趋势数据成功，社区ID列表：{}，趋势数据：{}", communityIds, trendData);
            return trendData;
        } catch (Exception e) {
            log.warn("获取用户注册趋势数据失败，社区ID列表：{}", communityIds, e);
            return generateEmptyDataList(months);
        }
    }
    
    @Override
    public Long getTotalUserCount() throws Exception {
        log.info("获取所有用户总数");
        
        try {
            // 统计所有启用的用户
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getStatus, SystemStatusEnum.ENABLED.getCode());
            
            long count = this.count(queryWrapper);
            log.info("获取所有用户总数成功，用户总数：{}", count);
            return count;
        } catch (Exception e) {
            log.warn("获取所有用户总数失败", e);
            return 0L;
        }
    }
    
    @Override
    public List<Integer> getUserRegistrationTrendForAll(int months) throws Exception {
        log.info("获取所有用户注册趋势数据，统计月份数：{}", months);
        
        try {
            // 这里需要根据实际的数据库表结构来实现
            // 暂时返回模拟数据
            List<Integer> trendData = new ArrayList<>();
            for (int i = 0; i < months; i++) {
                trendData.add((int) (Math.random() * 200 + 100)); // 模拟100-300之间的随机数
            }
            
            log.info("获取所有用户注册趋势数据成功，趋势数据：{}", trendData);
            return trendData;
        } catch (Exception e) {
            log.warn("获取所有用户注册趋势数据失败", e);
            return generateEmptyDataList(months);
        }
    }
    
    /**
     * 生成指定长度的空数据列表
     * 
     * @param size 列表大小
     * @return 填充0的列表
     */
    private List<Integer> generateEmptyDataList(int size) {
        List<Integer> emptyList = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            emptyList.add(0);
        }
        return emptyList;
    }

    @Override
    public AvatarUploadResponseDTO uploadAvatar(Long userId, MultipartFile file, AvatarUploadDTO uploadDTO) throws Exception {
        log.info("开始上传用户头像，用户ID: {}, 文件名: {}, 上传类型: {}", userId, file.getOriginalFilename(), uploadDTO.getUploadType());
        
        try {
            // 验证用户是否存在
            User user = this.getById(userId);
            if (user == null) {
                throw new BusinessException("用户不存在");
            }
            
            // 生成唯一的文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = getFileExtension(originalFilename);
            String fileName = generateUniqueFileName(userId, fileExtension);
            
            // 构建MinIO对象名称
            String objectName = buildAvatarFilePath(userId, fileName);
            
            // 保存文件到MinIO存储
            saveFileToMinIO(file, objectName);
            
            // 构建文件访问URL
            String fileUrl = buildFileUrl(objectName);
            
            // 创建响应DTO
            AvatarUploadResponseDTO response = new AvatarUploadResponseDTO();
            response.setId(System.currentTimeMillis()); // 临时ID，实际应该从文件表获取
            response.setFileUrl(fileUrl);
            response.setFileName(fileName);
            response.setFileSize(file.getSize());
            response.setFileType(file.getContentType());
            response.setFileExtension(fileExtension);
            response.setUploadType(uploadDTO.getUploadType());
            response.setUploadSource(uploadDTO.getUploadSource());
            response.setOriginalFileName(originalFilename);
            response.setFilePath(objectName);
            response.setUploadTime(LocalDateTime.now());
            response.setUploadUserId(userId);
            
            // 创建完整的文件信息JSON对象
            Map<String, Object> avatarFileInfo = new HashMap<>();
            avatarFileInfo.put("id", response.getId());
            avatarFileInfo.put("status", "success");
            avatarFileInfo.put("fileUrl", fileUrl);
            avatarFileInfo.put("fileName", fileName);
            avatarFileInfo.put("filePath", objectName);
            avatarFileInfo.put("fileSize", file.getSize());
            avatarFileInfo.put("fileType", file.getContentType());
            avatarFileInfo.put("createTime", LocalDateTime.now().toString());
            avatarFileInfo.put("uploadType", uploadDTO.getUploadType());
            avatarFileInfo.put("uploadSource", uploadDTO.getUploadSource());
            avatarFileInfo.put("fileExtension", fileExtension);
            avatarFileInfo.put("originalFileName", originalFilename);
            
            // 将文件信息转换为JSON字符串存储到avatar字段
            String avatarJson = convertToJsonString(avatarFileInfo);
            user.setAvatar(avatarJson);
            user.setUpdateTime(LocalDateTime.now());
            user.setUpdateBy(userId);
            this.updateById(user);
            
            // 缓存清理已通过@CacheEvict注解自动处理
            
            log.info("用户头像上传成功，用户ID: {}, 对象名称: {}, 文件URL: {}", userId, objectName, fileUrl);
            return response;
            
        } catch (Exception e) {
            // 根据异常类型进行不同的日志记录
            if (e instanceof BusinessException) {
                // 业务异常只记录消息，不打印堆栈
                log.warn("用户头像上传失败，用户ID: {}, 文件名: {}, 错误信息: {}", 
                    userId, file.getOriginalFilename(), e.getMessage());
            } else {
                // 系统异常记录完整信息
                log.error("用户头像上传失败，用户ID: {}, 文件名: {}, 错误信息: {}", 
                    userId, file.getOriginalFilename(), e.getMessage(), e);
            }
            throw e;
        }
    }
    
    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || !filename.contains(".")) {
            return "";
        }
        return filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
    }
    
    /**
     * 生成唯一文件名
     */
    private String generateUniqueFileName(Long userId, String extension) {
        long timestamp = System.currentTimeMillis();
        return String.format("avatar_%d_%d.%s", userId, timestamp, extension);
    }
    
    /**
     * 构建头像文件存储路径
     */
    private String buildAvatarFilePath(Long userId, String fileName) {
        // 使用MinIO存储，返回对象名称
        return String.format("avatar/%d/%s", userId, fileName);
    }
    
    /**
     * 保存文件到MinIO存储
     */
    private void saveFileToMinIO(MultipartFile file, String objectName) throws Exception {
        try {
            log.info("开始上传文件到MinIO，对象名称: {}", objectName);
            
            // 检查MinIO客户端是否可用
            if (minioClient == null) {
                throw new BusinessException("MinIO客户端未初始化，文件上传功能不可用");
            }
            
            // 上传到MinIO
            try (InputStream inputStream = file.getInputStream()) {
                minioClient.putObject(
                    PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(inputStream, file.getSize(), -1)
                        .contentType(file.getContentType())
                        .build()
                );
                log.info("文件上传到MinIO成功: bucket={}, object={}, size={}", bucketName, objectName, file.getSize());
            } catch (Exception e) {
                log.error("文件上传到MinIO失败: bucket={}, object={}, error={}", bucketName, objectName, e.getMessage(), e);
                throw new BusinessException("文件上传到MinIO失败: " + e.getMessage());
            }
            
        } catch (Exception e) {
            log.error("MinIO文件上传失败，对象名称: {}, 错误信息: {}", objectName, e.getMessage(), e);
            throw new BusinessException("MinIO文件上传失败: " + e.getMessage());
        }
    }
    
    /**
     * 构建文件访问URL
     */
    private String buildFileUrl(String objectName) {
        try {
            // 构建MinIO访问URL
            return String.format("%s/%s/%s", endpoint, bucketName, objectName);
            
        } catch (Exception e) {
            log.error("构建MinIO文件URL失败，对象名称: {}, 错误信息: {}", objectName, e.getMessage(), e);
            // 返回一个安全的默认URL
            return "/files/avatar/default.jpg";
        }
    }
    
    /**
     * 将Map转换为JSON字符串
     */
    private String convertToJsonString(Map<String, Object> data) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(data);
        } catch (Exception e) {
            log.error("JSON转换失败，数据: {}, 错误信息: {}", data, e.getMessage(), e);
            // 返回一个简单的JSON格式作为降级方案
            return "{\"error\":\"JSON转换失败\"}";
        }
    }
    
    @Override
    @Cacheable(value = "user:role:group", key = "#propertyCompanyId", unless = "#result == null || #result.isEmpty()")
    public List<UserByRoleGroupDTO> getUsersByRoleGroup(Long propertyCompanyId) throws Exception {
        log.info("开始根据物业公司ID获取按角色分组的用户列表，物业公司ID：{}", propertyCompanyId);
        
        try {
            // 参数校验
            if (propertyCompanyId == null || propertyCompanyId <= 0) {
                throw new BusinessException("物业公司ID必须大于0");
            }
            
            // 1. 获取该物业公司下的所有角色
            List<Map<String, Object>> roleList = baseMapper.getRolesByPropertyCompanyId(propertyCompanyId);
            if (roleList == null || roleList.isEmpty()) {
                log.info("物业公司{}下没有找到角色信息", propertyCompanyId);
                return new ArrayList<>();
            }
            
            // 2. 构建按角色分组的用户列表
            List<UserByRoleGroupDTO> result = new ArrayList<>();
            
            for (Map<String, Object> roleMap : roleList) {
                Long roleId = getLongValue(roleMap.get("roleId"));
                String roleName = getStringValue(roleMap.get("roleName"));
                String roleCode = getStringValue(roleMap.get("roleCode"));
                String roleDescription = getStringValue(roleMap.get("roleDescription"));
                Integer roleStatus = getIntegerValue(roleMap.get("status"));
                Integer sortOrder = getIntegerValue(roleMap.get("sortOrder"));
                
                if (roleId == null || roleName == null) {
                    log.warn("角色信息不完整，跳过：{}", roleMap);
                    continue;
                }
                
                // 3. 获取该角色下的用户列表
                List<Map<String, Object>> userList = baseMapper.getUsersByRoleIdAndPropertyCompanyId(roleId, propertyCompanyId);
                
                // 4. 转换为UserSimpleDTO列表
                List<UserSimpleDTO> users = new ArrayList<>();
                if (userList != null && !userList.isEmpty()) {
                    for (Map<String, Object> userMap : userList) {
                        UserSimpleDTO userSimple = new UserSimpleDTO();
                        userSimple.setId(getLongValue(userMap.get("id")));
                        userSimple.setUsername(getStringValue(userMap.get("username")));
                        userSimple.setRealName(getStringValue(userMap.get("realName")));
                        userSimple.setNickname(getStringValue(userMap.get("nickname")));
                        userSimple.setPhone(getStringValue(userMap.get("phone")));
                        userSimple.setEmail(getStringValue(userMap.get("email")));
                        userSimple.setAvatar(getStringValue(userMap.get("avatar")));
                        userSimple.setStatus(getIntegerValue(userMap.get("status")));
                        
                        users.add(userSimple);
                    }
                }
                
                // 5. 构建角色组DTO
                UserByRoleGroupDTO roleGroup = new UserByRoleGroupDTO();
                roleGroup.setRoleId(roleId);
                roleGroup.setRoleName(roleName);
                roleGroup.setRoleCode(roleCode);
                roleGroup.setRoleDescription(roleDescription);
                roleGroup.setRoleStatus(roleStatus);
                roleGroup.setSortOrder(sortOrder);
                roleGroup.setUserCount(users.size());
                roleGroup.setUsers(users);
                
                result.add(roleGroup);
            }
            
            // 6. 按排序顺序排序
            result.sort((a, b) -> {
                Integer sortA = a.getSortOrder() != null ? a.getSortOrder() : 0;
                Integer sortB = b.getSortOrder() != null ? b.getSortOrder() : 0;
                return sortA.compareTo(sortB);
            });
            
            log.info("根据物业公司ID获取按角色分组的用户列表成功，物业公司ID：{}，角色组数量：{}", 
                    propertyCompanyId, result.size());
            return result;
            
        } catch (Exception e) {
            log.error("根据物业公司ID获取按角色分组的用户列表失败，物业公司ID：{}，错误信息：{}", 
                    propertyCompanyId, e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 安全获取Long值
     */
    private Long getLongValue(Object value) {
        if (value == null) {
            return null;
        }
        if (value instanceof Long) {
            return (Long) value;
        }
        if (value instanceof Integer) {
            return ((Integer) value).longValue();
        }
        if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        return null;
    }
    
    /**
     * 安全获取String值
     */
    private String getStringValue(Object value) {
        if (value == null) {
            return null;
        }
        return value.toString();
    }
    
    /**
     * 安全获取Integer值
     */
    private Integer getIntegerValue(Object value) {
        if (value == null) {
            return null;
        }
        if (value instanceof Integer) {
            return (Integer) value;
        }
        if (value instanceof Long) {
            return ((Long) value).intValue();
        }
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        return null;
    }
} 